/*

Silly.C by Bill Buckels 2008.

Written by   : Bill Buckels
Email        : bbuckels@mts.net

Date Written : May 2008

Environment  : AppleX Manx Aztec C65 Version 3.2b
Windows XP Cross-development environment for ProDOS 8

I have made absolutely no attempt to make this program
compatible with any C compiler outside the AppleX
environment stated above.

Purpose Graphics Demo and Children's Play Activity

This program is based on "The Mixed-Up Toy game" from
Broderbund's PlayRoom program. "Three different
sections of the body--the head, torso, and legs spin
around and its up to the kids to change the body parts
to match the cartoon characters.,,"

It also offers a BSAVE option to save the Silly Things.

It is an Aztec C demo program to show how run length
encoded image fragments can be used to save disk space
and increase file load speed since the disk files are
smaller and load more quickly than a raw file, despite
the extra time required to decode the file onto the
screen.

The graphics images were captured from the 1989 MS-DOS
CGA 4 color version of The PlayRoom then saved to
BSaved IBM images using my ClipShop program which were
subsequently chopped into the required pieces using a
modified version of my Fraggle utility, I then modified
my FragRAG utility to provide a run length encoded
version of my RAG format that I call the RAX format.
This format is the same as the RAG format with the
exception that the graphics image data following the
width and height header is encoded as one chunk using
the ZSoft PCX encoding algorithm which is relatively
decent and unpacks quickly.

This program has a little history attached to it as
well. Around 1990 when my son was just a little guy I
would give him Apple II programs to take to school.

My kids had The Playroom on their IBM=PC. A
ComputerLand Salesman had given me an Okey-Dokey
Licenced Copy as a gift at one point when I was
purchasing a fair amount of software like compilers
around that time.

So I got busy and created "Billy's Silly Things" since
like me my son's name is Bill. I did so similarly to
what I have done here and wrote it in Aztec C for
ProDOS. I lond ago lost the code, and the program.

But with the resurrection of my Aztec C compiler I
decided that it would be nice to recreate this
program for a graphics demo, and of course for any kids
that you might be kicking around.

Licence Agreement
-----------------

All my work is copyrighted and belongs to me. I wrote
this program from scratch. However this program is a
derivative work in pretty much every way.

That notwithstanding this is also a programming demo,
albeit for an obsolete computer and a vanished market.

I herewith grant you a non-exclusive and conditional
licence to use this source code and the output files it
produces for whatever use you deem fit provided you do
not take credit for my work, and that you leave the
copyright notices intact in all of it.

If you augment or otherwise use my work you must always
also include your own personal copyright notice but it
may never be a GNU public licence or anything else that
resembles fascism or totalitarianism and
world-domination or a commercial or educational licence
either. You can use my stuff commercially or for GNU
with my conditions intact if they let you (they should
since copyright is for authors and the public and I
belong to both groups) but you must never copyright my
work with any company copyright whatsoever; just your
own personal copyright like mine and leave mine in
place. That is the way copyright is intended to work
and that is the way that it will work with my stuff
unless I selectively decide otherwise.

In addition you must agree that I am not liable in any
way shape or form for any damage from the use of any of
this in any way whatsoever.

If you do not agree with all of the aforementioned
conditions of use then remove all of this from your
computer now.

Bill Buckels
bbuckels@mts.net
May 2008

*/

#include <fcntl.h>
#include <stdio.h>

FILE *piclist=NULL;

/* G2 library extern */
extern unsigned HB[];

#define RAX_MAX 1607

/* 10 static silly things */
char *sillies[10] = {
	"DRAGON",
	"ROBOT",
	"CARROT",
	"RHINO",
	"ELEPHANT",
	"CLOWN",
	"FAIRY",
	"MOUSE",
	"FISH",
	"UNICORN"};


/* indices for top, middle, and bottom */
int tidx = 0, midx = 0, bidx = 0;
int todx = 0, modx = 0, bodx = 0;

/* screen co-ordinates xorg, yorg */
int sorg[3][2] = {
	3,0,
	3,64,
	3,134};

/* a read buffer */
unsigned char raxbuf[RAX_MAX];
unsigned char sillyname[41], proname[41], picname[66];

int bottom = 0;

char *menu1 = "TOP  - '1'  MIDDLE '2'  BOTTOM '3'";
char *menu2 = "MENU -  SPACEBAR        SAVE   'S'";

main()
{
	int c;

	setcrtmode(2);

	if (getch()!=27) {
		/* set-up initial screen */
		clear_bottom();
		setmem(0x4000,0x2000,0xff); /* white */
		show_silly(0);
		show_silly(1);
		show_silly(2);
		print_bottom(menu1,0,0);
		print_bottom(menu2,1,0);
		/* save line 2 for additional messages etc. */
		bottom = 1;
		mscreen(); /* start in mixed screen */

		for (;;) {
			c = toupper(getch());
			if (c == 27)break;
            /* remap keys */
			switch(c)
			{
				/* left and right arrow */
				case 21:
				case 8:
				        c =50; break; /* both remap to 2 */
				/* uparrow remaps to 1 */
				case 11: c = 49; break;

				case 10: c = 51; break;
				default: break;
			}

		    /* menu */
			if (c == 49 || c == 50 || c == 51) {
				show_silly(c-49);
			}
			if (c == 13 || c == 32) {
				if (bottom == 0) {
					mscreen();
					bottom = 1;
				}
				else {
					fscreen();
					bottom = 0;
				}
			}
			if (c == 'S')save_silly();
		}

	}
	setcrtmode(0);
    _exit();

}


/* save as an Apple II BSaved Image
   so it can be loaded in BASIC
   or viewed in other programs */
save_silly()
{
	int c, idx, oldbot = bottom, found = 0;

	clear_bottom();
	if (oldbot != 1)mscreen();
	bottom = 1;
	print_bottom("Put Data Disk into drive...",0,0);
	print_bottom("ENTER to SAVE.",1,0);
	print_bottom("Any other key to continue...",2,0);
	print_bottom(sillyname,3,0);

    c = getch();
    if (c == 13) {
		clear_bottom();
		print_bottom("Please Wait...",0,0);
		print_bottom(sillyname,3,0);
		c = bsave(proname);
		switch(c) {
			case -1: print_bottom("ERR Could not open...",0,0); bell(); break;
			case -2: print_bottom("ERR Could not write...",0,0); bell();break;
			default:

                     piclist=fopen("PICLIST","r");

                     if (piclist != NULL) {
						 fgets(picname,66,piclist); /* get the first filename */
						 while(picname[0]>' ' && picname[0] < '{')
						 {
						      idx=0;  /* replace carriage return with null */
						      while(picname[idx]!=0)
						      {
						      	if(picname[idx]< ' ')
						      	{
									picname[idx]= 0;
									break;
								}
						      	idx++;
						      }
						      idx=0;
						      found = 1;
							  while(proname[idx]!=0)
						      {
							  	 if(picname[idx] != proname[idx])
							  	 {
									 found = 0;
									 break;
								 }
							  	 idx++;
						      }
						      if (found == 1)break;
						      fgets(picname,66,piclist);
                          }
                          fclose(piclist);

				     }
				     piclist = NULL;
				     if (found == 0) {
			         	piclist=fopen("PICLIST","a");
			         	if (piclist != NULL) {
						 	fprintf(piclist,"%s\n",proname);
						 	fclose(piclist);
					 	}
					 	piclist = NULL;

				 	 }
					 print_bottom("Saved Silly Thing...",0,0);

		}
		print_bottom("Put Program Disk into drive...",1,0);
		print_bottom("Any key to continue...",2,0);
		getch();

	}
	else c = 0;

    if (oldbot != 1)fscreen();
    bottom = oldbot;
    clear_bottom();
    print_bottom(menu1,0,0);
	print_bottom(menu2,1,0);
	print_bottom(sillyname,3,0);

	return c;

}


/* display the image fragment in its
   logical position */
show_silly(sidx)
int sidx;
{
	int xorg, yorg,c,idx;
	char fname[20];

	if (tidx > 9)tidx = 0;
	if (midx > 9)midx = 0;
	if (bidx > 9)bidx = 0;
	switch(sidx)
	{
		case 0: strcpy(fname,(char *)&sillies[tidx][0]);
		        strcat(fname,"1.RAX");
		        todx = tidx;
		        tidx++;
		        break;
		case 1: strcpy(fname,(char *)&sillies[midx][0]);
		        strcat(fname,"2.RAX");
		        modx = midx;
		        midx++;
		        break;
		case 2: strcpy(fname,(char *)&sillies[bidx][0]);
		        strcat(fname,"3.RAX");
		        bodx = bidx;
		        bidx++;
		        break;

		default: return 0;

	}
	c = read_bin(fname,raxbuf);
	if(c== 0) {
        /* the new name will display if in mixed screen mode
           otherwise they can press the spacebar to toggle
           between fullscreen and mixed screen and they will
           see it then

		ProDOS allowed only fifteen characters in a
		filename compared to Apple DOS's thirty.

					*/

	    xorg = sorg[sidx][0];
	    yorg = sorg[sidx][1];
	    for (idx = 0; idx < 40; idx++)sillyname[idx] = 32;
	    sillyname[40] = 0;
	    print_bottom(sillyname,3,0);
        strcpy(sillyname,(char *)&sillies[todx][0]);
        strcpy(proname,(char *)&sillies[todx][0]);
        proname[5]=0;
        strcat(sillyname,".");
        strcat(sillyname,(char *)&sillies[modx][0]);
        strcat(proname,(char *)&sillies[modx][0]);
        proname[10]=0;
        strcat(sillyname,".");
        strcat(sillyname,(char *)&sillies[bodx][0]);
        strcat(proname,(char *)&sillies[bodx][0]);
        proname[15]=0;
	    print_bottom(sillyname,3,0);
	    put_rax(raxbuf,xorg,yorg);

	}
	else {
		bell();
	}
	return c;


}

/* read a RAX file */
read_bin(name,ptr)
char *name, *ptr;
{

   int fh, c=-1, limit = RAX_MAX +1, width, height;
   char head[2];

   fh = open(name,O_RDONLY,0xc3);
   if (fh == -1)return -1;
   c = read(fh,head, 2);
   if (c==2 && head[0] > 0 && head[1] > 0 && head[0] < 41 && head[1] < 193) {
	   c = read(fh,(char *)&ptr[2],RAX_MAX);
	   ptr[0] = head[0];
	   ptr[1] = head[1];
	   if (c > 0)c=0;
	   else c=-2;
   }
   else c = -2;
   close(fh);
   return c;
}

/* (C) Copyright Bill Buckels 2008 */

/* decode RAG images with pcx run-length ecoding */
/* directly onto screen */
/* these are chunk oriented and do not break on scanlines */
/* but the header provides the width and height so no problem */
/* slightly more efficient to encode these in chunks since
   repeats spanning scanlines encode more efficiently.*/
put_rax(ptr,xorg, yorg)
unsigned char *ptr;
int xorg,yorg;
{
	char *crt;
	unsigned char ch;
	int ctr=2, x, x1, xcnt,temp;
    int offset=0,width,height,target;

    width = ptr[0];
    height = ptr[1];
    target = (width * height);
    width = width + xorg;
    height = height + yorg;
    temp=HB[yorg];
    crt = (char *)(temp+xorg);
    x1 = xorg;

	do{

		/* start with a seed count */
		xcnt=1;
	    ch=ptr[ctr];
	    ctr++;

	    /* check to see if its raw */
	    /* if its not, run encoded */
	    if(0xC0 == (ch & 0xc0)){
	       xcnt = 0x3f & ch;
	       ch = ptr[ctr];
	       ctr++;
	    }
	    for(x=0;x<xcnt;x++){
			if (offset < target) {
				crt[x1] = ch;
				x1++;
				if (x1 >= width) {
					x1 = xorg;
					yorg++;
					if (yorg >= height)break;
					temp=HB[yorg];
					crt = (char *)(temp+xorg);
				}
			}
			else break;

			offset++;
		}

		if (yorg >= height)break;

     } while(offset<target);
     return 0;

}

